;(function(factory) {
	if (typeof define === "function" && define.amd) {
		// AMD模式
		define(["jquery"], factory);
	} else {
		// 全局模式
		factory(jQuery);
	}
}(function($) {
	var Cascrop = function(options, obj) {
		var self = this;
		var defaultOptions = {
			width: $(obj).width(),
			height: $(obj).height(),
			value: 0,
			min: 0,
			max: 20,
			onSelect: null,
			onChange: null
		}
		this.options = $.extend(defaultOptions, options);
		
		this.cropData = {
			x: 0,
			y: 0,
			w: this.options.width,
			h: this.options.height,
			scaleX: 1,
			scaleY: 1
		}
		
		this.zoomData = {
			zoomValue: 0
		}

		this.init = function() {
			var cascropTpl = '<div class="cascrop_holder unselect">' +
			'					  <image class="cascrop_avatar" src="' + window.parent.localInfo.avatPath + '"></image>' +
			'			          <image class="cascrop_target" style="display: none;"></image>' +
			'             	  </div>' +
			'                 <div class="cascrop_slider_bar unselect"></div>';
			$(cascropTpl).appendTo($(obj));
			$(obj).addClass("unselect");
			
			var sliderBar = $(obj).find(".cascrop_slider_bar"),
				cascropHolder = $(obj).find(".cascrop_holder");
			
			cascropHolder.css({
				width: self.options.width + "px",
				height: self.options.height + "px"
			});
			
			sliderBar.SliderBar({
				value: self.options.value,
				min: self.options.min,
				max: self.options.max,
				disabled: true,
				change: function(value) {
					self.zoomData.zoomValue = value;
					self.zoom();
				}
			});
		}

		this.setImage = function(imageData) {
			var imgEle = $(obj).find(".cascrop_target"),
				holderEle = $(obj).find(".cascrop_holder"),
			    defaultData = {
					imageUrl: "",
					imageWidth: 0,
					imageHeight: 0
				};
			

			if ($(obj).find(".cascrop_target").length > 0) {
				$(obj).find(".cascrop_target").empty();
			}
			
			self.imgData = $.extend(defaultData, imageData);
			self.cropData.w = self.options.width;
			self.cropData.h = self.options.height;
			
			holderEle.css({
				width: self.options.width + "px",
				height: self.options.height + "px"
			});
			imgEle.show();
			imgEle.attr({
				"src": self.imgData.imageUrl
			});
			
			self.zoomData.zoomValue = self.options.value;
			
			imgEle[0].onload = function() {
				self.zoom();
				self.updateCropData();
				
				imgEle.draggable({
					stop: function(e) {
						self.adjustImage();
						self.updateCropData();	
					}
				});
				
				$(obj).find(".cascrop_slider_bar").SliderBar("reset");
				$(obj).find(".cascrop_slider_bar").SliderBar("enable");
			}
		}
		
		this.adjustImage = function() {
			var top = parseInt($(obj).find(".cascrop_target").css("top")),
				left = parseInt($(obj).find(".cascrop_target").css("left")),
				width = parseInt($(obj).find(".cascrop_target").css("width")),
				height = parseInt($(obj).find(".cascrop_target").css("height")),
				rectWidth = self.options.width,
				rectHeight = self.options.height;
			
			if (width > rectWidth || height > rectHeight) {
				top = top > 0 ? 0 : top;
				top = top < -(height - rectHeight) ? -(height - rectHeight) : top;
				left = left > 0 ? 0 : left;
				left = left < -(width - rectWidth) ? -(width - rectWidth) : left;
			} else {
				top = 0;
				left = 0;
			}
			
			$(obj).find(".cascrop_target").css({
				top: top + "px",
				left: left + "px"
			});
		}
		
		this.zoom = function() {
			var imgEle = $(obj).find(".cascrop_target"),
				left = 0,
				top = 0,
				width = 0,
				height = 0,
				maxWidth = self.imgData.imageWidth,
				maxHeight = self.imgData.imageHeight,
				minWidth = self.options.width,
				minHeight = self.options.height;
			
			if (self.zoomData.zoomValue < self.options.min) {
				width = self.options.width;
				height = self.options.height;
			} else {
				var difValue = self.zoomData.zoomValue - self.options.min;
				var maxDif = self.options.max - self.options.min;
				var currentTop = parseInt(imgEle.css("top"));
				var currentLeft = parseInt(imgEle.css("left"));
				width = minWidth + (maxWidth - minWidth) * (difValue / maxDif);
				height = minHeight + (maxHeight - minHeight) * (difValue / maxDif);
				top = currentTop * (height / maxHeight);
				left = currentLeft * (width / minWidth);
			}
			
			width = width >= minWidth ? width : minWidth;
			height = height >= minHeight ? height: minHeight;
			
			if (maxWidth >= maxHeight)
			{
				width = maxWidth * height / maxHeight;
			}
			else
			{
				height = maxHeight * width / maxWidth;
			}
			
			
			
			setTimeout(function() {
				imgEle.css({
					top: top,
					left: left,
					width: width,
					height: height
				});
				
				self.adjustImage();
				self.updateCropData();
			}, 100);
		}
		
		this.updateCropData = function() {
			var imgEle = $(obj).find(".cascrop_target");
			
			self.cropData.x = Math.abs(parseInt(imgEle.css("left")));
			self.cropData.y = Math.abs(parseInt(imgEle.css("top")));
			self.cropData.scaleX = parseInt(imgEle.css("width")) / self.imgData.imageWidth;
			self.cropData.scaleY = parseInt(imgEle.css("height")) / self.imgData.imageHeight;
			
			//calculate rel data
			self.cropData.x = Math.round(self.cropData.x / self.cropData.scaleX);
			self.cropData.y = Math.round(self.cropData.y / self.cropData.scaleY);
			self.cropData.w = Math.round(self.options.width / self.cropData.scaleX);
			self.cropData.h = Math.round(self.options.height / self.cropData.scaleY);
			
			if (typeof self.options.onChange == "function") {
				self.options.onChange(self.cropData);
			}
		}

		this.init();
		
		return this;
	}
	
	$.fn.Cascrop = function(params, callback) {
		var el = this[0];
		if (typeof params == "object") {
			el.cascrop = new Cascrop(params, el);
		}
		
		if (typeof callback == "function") {
			callback.call(el.cascrop);
		}
		
		return this;
	}
	
	var SliderBar = function(options, obj) {
		var self = this;
		
		var defaultOptions = {
			value: 0,
			min: 0,
			max: 0,
			disabled: false,
			change: null
		}
		
		this.options = $.extend(defaultOptions, options);
		this.slider = {
			ui: {
				value: self.options.value
			},
			state: {
				isOnSlider: false,
				isDispatch: true,
				disabled: self.options.disabled
			},
			screenX: 0,
			sliderLength: 0,
			segmentLength: 0,
			dispatchTimer: null
		}
		
		this.init = function() {
			self.initUI();
			self.initEvent();
			self._prepareData();
			self._setValue(self.options.value, true);
		}
		
		this.initUI = function() {
			var sliderHtml = '<div class="slider-bar-holder">' +
				'                 <div class="slider-bar-zoom-out unselect"></div>' +
				'				  <div class="slider-bar-control unselect">' +
				'				      <div class="slider-bar-slider">' +
				'					      <div class="slider-bar-range"></div>' +
				'                         <div class="slider-bar-handler"></div>' +
				'				      </div>' +
				'				  </div>' +
				'			      <div class="slider-bar-zoom-in unselect"></div>' +
				'			  </div>';
			$(obj).append($(sliderHtml));
		}
		
		this.initEvent = function() {
			$(obj).on("click", ".slider-bar-zoom-out", function() {
				self._setValue(self.slider.ui.value-1);
			}).on("click", ".slider-bar-zoom-in", function() {
				self._setValue(self.slider.ui.value+1);
			}).on("click", ".slider-bar-control", function(e) {
				self._stopBubble(e);
				self._setPos(e.clientX - self.slider.screenX);
			}).on("mousedown", ".slider-bar-handler", function(e) {
				self._stopBubble(e);
				self.slider.state.isOnSlider = true;
			}).on("mouseup", ".slider-bar-handler", function(e) {
				self._stopBubble(e);
				self.slider.state.isOnSlider = false;
			});
			
			window.onmouseup = function(e) {
				self._stopBubble(e);
				self.slider.state.isOnSlider = false;
			}
			
			window.onmousemove = function(e) {
				self._stopBubble(e);
				if (self.slider.state.isOnSlider //滑块点击状态
					&& self._isOnMousedown(e) //保证有鼠标左键按下
					&& e.offsetX >= 0 //鼠标在windows窗口之内
					&& e.clientX - self.slider.screenX >= 0 //x坐标在滚动条范围内
					&& e.clientX - self.slider.screenX <= self.slider.sliderLength) {
					self._setPos(e.clientX - self.slider.screenX);
				}
			}
		}
		
		this._isOnMousedown = function(e) {
			var result = false;
			
			if(navigator.userAgent.indexOf("MSIE") > -1) {
				if (window.event.button == 1) {
					result = true;
				}
			} else if (navigator.userAgent.indexOf("Firefox") > -1) {
				if (e.buttons == 1) {
					result = true;
				} else {
					result = false;
				}
			} else if (navigator.userAgent.indexOf("Chrome") > -1) {
				if (e.buttons == 1) {
					result = true;
				}
			} else {
				result = true;
			}
			
			if (!result) {
				self.slider.state.isOnSlider = false;
			}
			
			return result;
		}
		
		this._stopBubble = function(e) {
			if (e && e.stopPropagation) {
				e.stopPropagation();
			} else {
				window.event.cancelBubble = true;
			}
		}
		
		this._prepareData = function() {
			self.slider.screenX = self._getX($(obj).find(".slider-bar-slider")[0]);
			self.slider.sliderLength = parseInt($(obj).find(".slider-bar-slider").width());
			self.slider.segmentLength = self.slider.sliderLength / (self.options.max - self.options.min);
		}
		
		this._setValue = function(value, isInit) {
			if (!isInit) {
				if (self.slider.state.disabled) {
					return;
				}
				
				if (value > self.options.max || value < self.options.min) {
					return;
				}
			}
			
			self._updateSlider(value * self.slider.segmentLength, isInit);
		}
		
		this._setPos = function(pos) {
			if (self.slider.state.disabled) {
				return;
			}
			
			self._updateSlider(pos);
		}
		
		this._updateSlider = function(pos, isInit) {
			if (pos > self.slider.sliderLength || pos < 0) {
				return;
			}
			
			var perBlock = self.slider.segmentLength;
			var targetBlock = Math.ceil(pos / perBlock);
			var delValue1 = pos - (targetBlock - 1) * perBlock;
			var delValue2 = targetBlock * perBlock - pos;
			if (delValue1 <= delValue2) {
				pos = (targetBlock - 1) * perBlock;
				self.slider.ui.value = targetBlock - 1;
			} else {
				pos = targetBlock * perBlock;
				self.slider.ui.value = targetBlock;
			}
			
			$(obj).find(".slider-bar-handler").css("left", pos + "px");
			$(obj).find(".slider-bar-range").css("width", pos + "px");
			
			if (typeof self.options.change == "function" && self.slider.state.isDispatch && !isInit) {
				self.options.change(self.slider.ui.value);
				
				self.slider.state.isDispatch = false;
				self.slider.dispatchTimer = setTimeout(function() {
					self.slider.state.isDispatch = true;
				}, 20);
			}
		}
		
		this._getX = function(obj) {
			return obj.offsetLeft + (obj.offsetParent ? this._getX(obj.offsetParent) : obj.x ? obj.x : 0);
		}
		
		this.disable = function() {
			self.slider.state.disabled = true;
		}
		
		this.enable = function() {
			self.slider.state.disabled = false;
		}
		
		this.reset = function() {
			self._setValue(self.options.value, true);
		}
		
		this.init();
		
		return this;
	}
	
	$.fn.SliderBar = function(params) {
		var el = this[0];
		if (typeof params == "object") {
			el.cascrop = new SliderBar(params, el);
		} else if (typeof params == "string") {
			switch (params) {
				case "disable": {
					el.cascrop.disable();
					break;
				}
				case "enable": {
					el.cascrop.enable();
					break;
				}
				case "reset": {
					el.cascrop.reset();
				}
				default: {
					break;
				}
			}
		}
		
		return this;
	}
}));